home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / uwserver.zip / uwserver.tar / lib / uw_fork.c < prev    next >
C/C++ Source or Header  |  1991-01-25  |  5KB  |  194 lines

  1. /*
  2.  *    uw library - uw_fork
  3.  *
  4.  * Copyright 1986 by John D. Bruner.  All rights reserved.  Permission to
  5.  * copy this program is given provided that the copy is not sold and that
  6.  * this copyright notice is included.
  7.  */
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <sys/un.h>
  11. #include <sys/ioctl.h>
  12. #include <sys/uio.h>
  13. #include <sys/file.h>
  14. #include <strings.h>
  15. #include <signal.h>
  16. #include "openpty.h"
  17.  
  18. #include "uwlib.h"
  19.  
  20. extern char *malloc();
  21. extern char *getenv();
  22.  
  23. uwid_t
  24. uw_fork(wtype, pidp)
  25. uwtype_t wtype;
  26. int *pidp;
  27. {
  28.     register int pid;
  29.     register int sd;
  30.     register struct uwipc *uwip;
  31.     register uwid_t wid;
  32.     auto int fd;
  33.     char *portal;
  34.     int lmode, ldisc;
  35.     struct sgttyb sg;
  36.     struct tchars tc;
  37.     struct ltchars ltc;
  38.     struct iovec iov;
  39.     struct msghdr msg;
  40.     struct sockaddr_un sa;
  41.     struct ptydesc pt;
  42.     char idstr[20];
  43.     char *env[2];
  44.     extern char *ltoa();
  45.  
  46.     /*
  47.      * Create a new window attached to a pseudo-terminal.  This routine
  48.      * returns twice -- once in the parent and once in the (new) child.
  49.      * The parent receives the window ID of the child (or -1 if the
  50.      * window creation failed).  Zero is returned to the child.
  51.      * If "pidp" is a non-NULL pointer, the process ID from the fork()
  52.      * is stored there.
  53.      */
  54.  
  55.     /*
  56.      * Get the terminal configuration for this tty.  For now we
  57.      * assume that "/dev/tty" is defined.  Eventually we'll have to
  58.      * provide defaults in case it is not.
  59.      */
  60.     if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
  61.         (void)ioctl(fd, (int)TIOCGETP, (char *)&sg);
  62.         (void)ioctl(fd, (int)TIOCGETC, (char *)&tc);
  63.         (void)ioctl(fd, (int)TIOCGLTC, (char *)<c);
  64.         (void)ioctl(fd, (int)TIOCLGET, (char *)&lmode);
  65.         (void)ioctl(fd, (int)TIOCGETD, (char *)&ldisc);
  66.         (void)close(fd);
  67.     } else {
  68.         /* ... */
  69.     }
  70.  
  71.     /*
  72.      * Create a UNIX-domain socket.
  73.      */
  74.     if (!(portal=getenv("UW_UIPC"))) {
  75.         uwerrno = UWE_NXSERV;
  76.         return(-1);
  77.     }
  78.  
  79.     if ((sd=socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
  80.         uwerrno = UWE_ERRNO;
  81.         return(-1);
  82.     }
  83.     sa.sun_family = AF_UNIX;
  84.     (void)strncpy(sa.sun_path, portal, sizeof sa.sun_path-1);
  85.     sa.sun_path[sizeof sa.sun_path-1] = '\0';
  86.  
  87.  
  88.     /*
  89.      * Obtain a pseudo-tty and construct the datagram we will send later.
  90.      */
  91.     if (openpty(&pt) < 0) {
  92.         uwerrno = UWE_ERRNO;
  93.         return(-1);
  94.     }
  95.     uwip = (struct uwipc *)malloc(sizeof(struct uwipc)+strlen(pt.pt_pname));
  96.     env[0] = malloc(sizeof "UW_ID=" + sizeof idstr);
  97.     if (uwip == (struct uwipc *)0 || env[0] == (char *)0) {
  98.         uwerrno = UWE_NOMEM;
  99.         return(-1);
  100.     }
  101.     uwip->uwip_cmd = UWC_NEWT;
  102.     uwip->uwip_len = (char *)&uwip->uwip_newt - (char *)uwip +
  103.         sizeof(struct uwnewt) + strlen(pt.pt_pname);
  104.     uwip->uwip_newt.uwnt_type = wtype;
  105.     (void)strcpy(uwip->uwip_newt.uwnt_pty, pt.pt_pname);
  106.  
  107.  
  108.     /* 
  109.      * Fork a child process using this pseudo-tty.  Initialize the
  110.      * terminal modes on the pseudo-tty to match those of the parent
  111.      * tty.  We really want a fork() here, not a vfork().
  112.      */
  113.     while ((pid=fork()) < 0)
  114.         sleep(5);
  115.     if (pidp != (int *)0)
  116.         *pidp = pid;
  117.     if (pid) {
  118.         wid = (long)pid << 16;
  119.         uwip->uwip_newt.uwnt_id = wid;
  120.     } else {
  121.         (void)setgid(getgid());
  122.         (void)setuid(getuid());
  123.         wid = (long)getpid() << 16;
  124.         (void)strcat(strcpy(env[0], "UW_ID="),
  125.              ltoa(wid, idstr, sizeof idstr));
  126.         env[1] = (char *)0;
  127.         env_set(env);
  128.         (void)signal(SIGTSTP, SIG_IGN);
  129.         (void)ioctl(open("/dev/tty", 2), (int)TIOCNOTTY, (char *)0);
  130.         (void)close(open(pt.pt_tname, 0)); /*set new ctrl tty */
  131.         (void)dup2(pt.pt_tfd, 0);
  132.         (void)dup2(0, 1);
  133.         (void)dup2(0, 2);
  134.         fd = getdtablesize();
  135.         while (--fd > 2)
  136.             (void)close(fd);
  137.         (void)ioctl(fd, (int)TIOCSETD, (char *)&ldisc);
  138.         (void)ioctl(0, (int)TIOCSETN, (char *)&sg);
  139.         (void)ioctl(0, (int)TIOCSETC, (char *)&tc);
  140.         (void)ioctl(0, (int)TIOCSLTC, (char *)<c);
  141.         (void)ioctl(0, (int)TIOCLSET, (char *)&lmode);
  142.         uwerrno = UWE_NONE;
  143.         return(0);
  144.     }
  145.  
  146.  
  147.     /*
  148.      * Pass the file descriptor to the window server.
  149.      */
  150.     iov.iov_base = (char *)uwip;
  151.     iov.iov_len = uwip->uwip_len;
  152.     msg.msg_name = (caddr_t)&sa;
  153.     msg.msg_namelen = sizeof sa.sun_family + strlen(sa.sun_path);
  154.     msg.msg_iov = &iov;
  155.     msg.msg_iovlen = 1;
  156.     msg.msg_accrights = (caddr_t)&pt.pt_pfd;
  157.     msg.msg_accrightslen = sizeof pt.pt_pfd;
  158.     if (sendmsg(sd, &msg, 0) < 0) {
  159.         free((char *)uwip);
  160.         uwerrno = UWE_ERRNO;
  161.         return(-1);
  162.     }
  163.     free((char *)uwip);
  164.     uwerrno = UWE_NONE;
  165.     return(wid);
  166. }
  167.  
  168. static
  169. char *
  170. ltoa(l, buf, buflen)
  171. long l;
  172. char *buf;
  173. int buflen;
  174. {
  175.     register char *cp;
  176.     register unsigned long ul;
  177.     static char digits[] = "0123456789";
  178.  
  179.     /*
  180.      * This routine replaces a call to sprintf() so that the library
  181.      * is independent of stdio.
  182.      */
  183.     cp = buf+buflen;
  184.     *--cp = '\0';
  185.     ul = l;
  186.     if (cp > buf) {
  187.         do {
  188.             *--cp = digits[ul%10];
  189.             ul /= 10;
  190.         } while (cp > buf && ul != 0);
  191.     }
  192.     return(cp);
  193. }
  194.